#pragma once
#include <iostream>
#include <cstring>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <jsoncpp/json/json.h>

#define SEP " "
#define SEP_LEN strlen(SEP) // sizeof 计算长度的时候会加上/n   而strlen 只计算字符的个数
#define LINE_SEP "\r\n"
#define LINE_SEP_LEN strlen(LINE_SEP)
enum
{
    PERICOUS = 0,
    DIV_ZERO,
    MOD_ZERO,
    INPUT_ERROR
};
// 增加字长去区分正文和标记
// 发送字节流的格式是  “content_len\r\ncontent\r\n”
std::string enLength(const std::string &str)
{
    std::string res_text = std::to_string(str.size());
    res_text+=LINE_SEP;
    res_text+=str;
    res_text+=LINE_SEP;

    return res_text;
}
//去掉前面的“content_len\r\ncontent\r\n” -->content_len，将内容存储在req_str中
bool deLength(std::string &str, std::string *req_str)
{
    auto pos = str.find(LINE_SEP);
    if(pos ==std::string::npos) return false;
    std::string content_len = str.substr(0,pos);
    ssize_t len = std::stoi(content_len);
    //这里求出来的是内容的长度
    *req_str=str.substr(pos+LINE_SEP_LEN,len);
    return true;

}
//没有人堆顶网络通信的饿时候，之规定一种协议
//怎么让系统知道我们使用的是哪一种协议 呢
// x + y ------->res
// 因为TCP是全双工的，所以对于string的数据需要把他转化成 x op y的形式
class Request
{
public:
    Request()
        : _x(0), _op('+'), _y(0)
    {
    }
    Request(int x, char op, int y)
        : _x(x), _op(op), _y(y)
    {
    }
    // 1. 序列化---》1.自己写  2. 用现成的
    //  "x + y" 需要转换成这样的形式，然后转成字节流传送给服务端   --序列化
    bool serialize(std::string *expression) // 输入输出型参数
    {
#ifdef MYSELF
        *expression = std::to_string(_x);
        *expression += SEP;
        *expression += _op;
        *expression += SEP;
        *expression += std::to_string(_y);
#else
    Json::Value root;
    root["first"] = _x;
    root["op"] = _op;
    root["second"]=_y;

    Json::FastWriter writer;
    *expression = writer.write(root);

#endif
        return true;
    }

    // "x + y /t/n" 的string 类型的对象，需要将他拆成 _x _op _y的格式   --反序列化
    bool deserialize(const std::string &str)
    {
#ifdef MYSELF
        size_t left = str.find(SEP);
        size_t right = str.rfind(SEP);
        if (left == std::string::npos || right == std::string::npos)
            return false;
        if (left == right)
            return false;
        if (right - (left + SEP_LEN) != 1)
            return false;
        
        std::string x_string = str.substr(0,left);
        std::string y_string = str.substr(right+SEP_LEN);
        if(x_string.empty() || y_string.empty()) return false;


        _x = std::stoi(x_string);
        _y = std::stoi(y_string);
        _op = str[left + SEP_LEN];
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(str,root);

        _x=root["first"].asInt();
        _y=root["second"].asInt();
        _op=root["op"].asInt();



#endif
        return true;
    }

    ~Request() {}

public:
    int _x;
    char _op;
    int _y;
};

//
class Response
{
public:
    Response()
        : _exitcode(0), _exitrest(0)
    {
    }
    Response(const int &exitrest, const int &exitcode)
        : _exitcode(exitcode), _exitrest(exitrest)
    {
    }
    // 把response 的exitcode 和exitresult 包装成字符串传出去，用于网络层的传输
    //"exitcode exitresult"
    bool serialize(std::string *expression)
    {
#ifdef MYSELF
        *expression += std::to_string(_exitcode);
        *expression += SEP;
        *expression += std::to_string(_exitrest);
#else

        Json::Value root;
        root["_exitrest"] = _exitrest;
        root["_exitcode"] = _exitcode;


        Json::FastWriter writer;
        *expression = writer.write(root);

#endif
        return true;
    }
    //把"exitcode exitresult"的字符串进行分割
    bool deserialize(std::string &str)
    {
#ifdef MYSELF
        auto pos = str.find(SEP);
        if(pos == std::string::npos)    return false;
        std::string ec_string =str.substr(0,pos);
        std::string res_string =str.substr(pos+SEP_LEN);
        if(ec_string.empty() || res_string.empty()) return false;

        _exitcode = std::stoi(ec_string);
        _exitrest = std::stoi(res_string);
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(str,root);

        _exitrest=root["_exitrest"].asInt();
        _exitcode=root["_exitcode"].asInt();
#endif
        return true;
    }
    ~Response() {}

public:
    int _exitrest;  //计算的结果
    int _exitcode; // 0 表示计算结果正确   1 表示除法除数为0 或者%运算有0
};


//content_len\r\ncontent\r\n content_len\r\ncontent\r\ncontent_len\r\ncontent\r\ncontent_len\r\ncontent\r\n
bool recvRequest(const int sock,std::string &inbuffer,std::string *req_text)
{
    char buffer[1024];
    while(true)
    {
        ssize_t num = recv(sock,buffer,sizeof(buffer)-1,0);
        if(num>0)
        {
            buffer[num]=0; //给尾部置0
            inbuffer+=buffer; 
            std::cout << "读取到的inbuffer: " << inbuffer << std::endl;
            auto pos = inbuffer.find(LINE_SEP);
            if(pos == std::string::npos) continue;
            //就是读到了第一个/r/n
            //首先计算出正文的长度
            std::string len_str = inbuffer.substr(0,pos);
            int len_content = std::stoi(len_str);
            int total_len = len_str.size()+2*LINE_SEP_LEN+len_content;
            std::cout << "处理前#inbuffer: " << inbuffer << std::endl;
            if(inbuffer.size()<total_len)
            {
                std::cout<<"输入的消息未遵守协议，正在等待后续内容"<<std::endl;
                continue;
            }
            //至少由一个完整的报文  //已经将正文内容读取到了text_content中
            *req_text= inbuffer.substr(0,total_len);
            //抹去已经读取到的一个完整的报文
            std::cout<<"从inbuffer中读取到的数据"<<*req_text<<std::endl;
            inbuffer.erase(0,total_len);

            std::cout<<"处理后#inbuffer:"<<inbuffer<<std::endl;
            break;
        }
        else
        {
            return false;
        }
            
    }
    return true;
}